home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright 1990, Brown University, Providence, RI. *
- * Permission to use, copy, modify and distribute this software and *
- * its documentation for any purpose other than its incorporation *
- * into a commercial product, is hereby granted, provided that this *
- * copyright notice appears on all copies. *
- * *
- ************************************************************************/
- /************************************************************************
- * *
- * speak.c *
- * *
- ************************************************************************/
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/stat.h>
- #include <audio/audiolib.h>
- #include <audio/soundlib.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <stdio.h>
-
- #define getwd(x) getcwd(x, 1024)
-
- static int volume = 100;
-
- #define VOL(volume) (int)((1 << 16) * (volume) / 100)
-
- /************************************************************************
- * *
- * type and array of phoneme audio samples *
- * *
- ************************************************************************/
- typedef struct phoneme_t
- {
- int size;
- char *data;
- char *fname;
- Sound sound_hdr;
- };
-
- static struct phoneme_t phoneme[1024];
-
- /************************************************************************
- * *
- * names of known phonemes *
- * *
- ************************************************************************/
- static
- char *phoneme_name[] = {
- "IY", "EY", "AE", "AO", "UH",
- "ER", "AH", "AW", "IH", "EH",
- "AA", "OW", "UW", "AX", "AY",
- "OY", "YU", "p", "t", "k", "f",
- "TH", "s", "SH", "HH", "n",
- "l", "y", "CH", "WH", "b",
- "d", "g", "v", "DH", "z",
- "ZH", "m", "NG", "w", "r", "j",
- (char *) 0
- };
-
- extern FILE *In_file; /* from parse.c */
- extern char *sys_errlist[];
-
- static char *buffer;
- static int curfd;
-
- AuServer *aud;
-
- speak_load_samples(dir)
- char *dir;
- {
- register i, k, rv;
- char *cp;
- char cwd[1024];
- DIR *dirp;
- struct dirent *dp;
- struct stat st;
- Sound ah;
- static char tmp[BUFSIZ];
-
- if ((dirp = opendir(dir)) == 0)
- return fatal(0, "can't open directory %s", dir);
-
- (void) getwd(cwd);
- if (chdir(dir))
- return fatal(0, dir);
-
- while (dp = readdir(dirp))
- {
- for (cp = phoneme_name[i = 0];
- cp && strcmp(dp->d_name, cp) != 0;
- cp = phoneme_name[++i]);
- if (cp == (char *) 0)
- continue;
-
- i = ch_to_code(&cp);
-
- #ifdef USE_PLAYDATA
- if ((ah = SoundOpenFileForReading(dp->d_name)) == (Sound) 0)
- return fatal(0, dp->d_name);
- if (phoneme[i].data)
- free(phoneme[i].data);
- phoneme[i].size = SoundNumBytes(ah);
- phoneme[i].sound_hdr = ah;
-
- if ((phoneme[i].data = (char *) malloc(phoneme[i].size)) == 0)
- return fatal(0, "malloc returned zero");
-
- SoundReadFile (phoneme[i].data, phoneme[i].size, phoneme[i].sound_hdr);
-
- SoundCloseFile (phoneme[i].sound_hdr);
- #else
- strcpy (tmp, dir);
- strcat (tmp, "/");
- strcat (tmp, dp->d_name);
- if ((phoneme[i].fname = malloc (strlen (tmp) + 1)) == 0)
- return fatal(0, "malloc returned zero");
- strcpy(phoneme[i].fname, tmp);
- #endif
-
- }
- closedir(dirp);
-
- for (cp = phoneme_name[i = 0]; cp; cp = phoneme_name[++i])
- {
- k = ch_to_code(&cp);
- #ifdef USE_PLAYDATA
- if (phoneme[k].size == 0)
- return fatal(0, "zero length phoneme '%s'", phoneme_name[i]);
- #else
- if (phoneme[k].fname == NULL)
- return fatal(0, "No filename for phoneme '%s'", phoneme_name[i]);
-
- #endif
- }
-
- if (chdir(cwd))
- return fatal(0, cwd);
-
- return 0;
- }
-
- speak_string(str)
- char *str;
- {
- buffer = str;
- xlate_file(); /* hook into eng_to_phoneme code */
- buffer = (char *) 0;
-
- return 0;
- }
-
- speak_volume(vol)
- int vol;
- {
- volume = vol;
- }
-
- speak_close(fd)
- int fd;
- {
- close(fd);
-
- return 0;
- }
-
- hacked_getc(fp)
- FILE *fp;
- {
- static ix;
-
- if (In_file)
- return getc(fp);
-
- if (buffer[ix] == 0)
- {
- ix = 0;
- return EOF;
- }
- else
- return buffer[ix++];
- }
-
- phoneme_str_to_audio(cp)
- char *cp;
- {
- register i;
- AuEventHandlerRec *Rec;
-
- while (*cp)
- if (isspace(*cp))
- {
- cp++;
- speak_delay(0);
- }
- else
- {
- i = ch_to_code(&cp);
- #ifdef USE_PLAYDATA
- Rec = AuSoundPlayFromData(aud, phoneme[i].sound_hdr,
- phoneme[i].data, AuNone, volume, (void (*))0,
- (void *)0, (AuFlowID *)0, (int *)0, (int *)0,
- (AuStatus *)0);
- #else
- AuSoundPlaySynchronousFromFile(aud, phoneme[i].fname, volume);
- #endif
-
- }
- }
-
- /************************************************************************
- * *
- * ch_to_code *
- * code_to_ch *
- * *
- * Map a phoneme name to a unique index between 1 and 1023, or *
- * vice versa. Ch_to_code advances it's argument to the next *
- * phoneme (or null). Code_to_ch returns a null-terminated *
- * string. *
- * *
- ************************************************************************/
- int
- ch_to_code(cp)
- char **cp;
- {
- register char *tp = *cp;
-
- if (islower(*tp))
- {
- *cp += 1;
- return *tp - 'a' + 1;
- }
- else
- {
- *cp += 2;
- return ((*tp - 'A' + 1) << 5) | (*(tp + 1) - 'A' + 1);
- }
- }
-
- char *
- code_to_ch(code)
- int code;
- {
- static char ch[3];
-
- if (code < (1 << 5))
- {
- ch[1] = code + 'a' - 1;
- return &ch[1];
- }
- else
- {
- ch[0] = (code >> 5) + 'A' - 1;
- ch[1] = (code & 0x1f) + 'A' - 1;
- return &ch[0];
- }
- }
-
- /************************************************************************
- * *
- * speak_delay *
- * *
- * Flush the audio device and pause for the given interval. *
- * If no interval is specified, pause for 2/10 second. *
- * *
- ************************************************************************/
- speak_delay(delay)
- int delay; /* in 10ths of a second */
- {
- static struct timeval tv = {0, 200000}; /* 1sec == 1000000 usec */
-
- if (delay)
- tv.tv_usec = delay * 100000;
- (void) AuFlush(aud);
- (void) select(0, 0, 0, 0, &tv);
-
- return 0;
- }
-
- int
- fatal(code, str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- int code;
- char *str;
- int a1, a2, a3, a4, a5, a6, a7, a8, a9;
- {
- char *bp;
- char b1[256], b2[256];
-
- bp = (char *) sprintf(b1, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- #if 0
- if (code)
- switch (code)
- {
- case AUDIO_UNIXERROR:
- bp = (char *) sprintf(b2, "%s: %s", str, sys_errlist[errno]);
- break;
- case AUDIO_ERR_BADHDR:
- bp = (char *) sprintf(b2, "%s: bad audio header", str);
- break;
- case AUDIO_ERR_BADFILEHDR:
- bp = (char *) sprintf(b2, "%s: bad file header", str);
- break;
- case AUDIO_ERR_BADARG:
- bp = (char *) sprintf(b2, "%s: bad subroutine argument", str);
- break;
- case AUDIO_ERR_NOEFFECT:
- bp = (char *) sprintf(b2, "%s: device control ingnored", str);
- break;
- case AUDIO_ERR_ENCODING:
- bp = (char *) sprintf(b2, "%s: unknown encoding format", str);
- break;
- case AUDIO_ERR_INTERRUPTED:
- bp = (char *) sprintf(b2, "%s: operation was interrupted", str);
- break;
- default:
- bp = (char *) sprintf(b2, "%s: <unknown error code>", str);
- break;
- }
- #endif
-
- fprintf(stderr, "%s\n", bp);
-
- return -1;
- }
-